////////////////////////////////////////////////////////////////
// February 2012
// If this code works, it was written by Francesco Feltrin, Eng. Phd.
// If not, I don't know who wrote it.
// Compiles with Visual Studio 2008 on Windows 7. 
//
#include "stdafx.h"
#include "volume_master.hpp"

#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>


std::string const volume_master::get_mount_point(std::string const& _volume_name)
{
	std::string drive("");
	std::vector<std::string> _mounted_list;
	if(int num = get_logical_drive_strings(_mounted_list))
	{
		int k;
		for(k=0; k < num; k++)
		{
			std::string volname;
			get_volume_information(_mounted_list[k], volname);
			if(_volume_name == boost::algorithm::to_upper_copy<std::string>(volname)) break;
		}
		if(k < num)
			drive = _mounted_list[k];
	}

	return (drive = boost::algorithm::to_upper_copy<std::string>(drive));
}

#ifdef WIN32
#include <tchar.h>
#include <atlbase.h>
#endif

int volume_master::get_logical_drive_strings(std::vector<std::string>& v)
{
	int num(0);

#ifdef WIN32
	const int BUFLEN = 26*4;
	TCHAR buf[BUFLEN+1];
	::GetLogicalDriveStrings(BUFLEN, buf);

	for (LPCTSTR drive=buf; *drive; drive += _tcslen(drive)+1) {
		std::string s = CT2A(drive); // conversion here from LPCTSTR
		v.push_back(s);
	}
	num = v.size();
#endif

	return num;
}

//////////////////
// Get logical drive info using std::string instead of LPTSTR buffers.
//
bool volume_master::get_volume_information(
	std::string const& _drive,
	std::string& _volname)
{
	bool res(false);

#ifdef WIN32
	TCHAR volname[_MAX_FNAME+1];
	LPTSTR lpVolumeNameBuffer = volname;

	TCHAR filesys[_MAX_FNAME+1];
	LPTSTR lpFileSystemNameBuffer = filesys;

	DWORD VolumeSerialNumber;
	DWORD MaximumComponentLength;
	DWORD FileSystemFlags;

	USES_CONVERSION;
	LPCTSTR lpRootPathName = A2CT(_drive.c_str());

	BOOL bRet= ::GetVolumeInformation(
		lpRootPathName,
		lpVolumeNameBuffer, _MAX_FNAME,
		&VolumeSerialNumber,
		&MaximumComponentLength,
		&FileSystemFlags,
		lpFileSystemNameBuffer, _MAX_FNAME);


	_volname =  CT2A(lpVolumeNameBuffer);
	res = bRet == TRUE? true: false;
#endif

	return	res;
}

#include <boost/algorithm/string.hpp>

char volume_master::get_volume_letter(std::string const& _volume_name)
{
	std::string volume(get_mount_point(_volume_name));
	char c(' ');
	
	if(!volume.empty())
	{
		boost::trim(volume);
		boost::algorithm::to_upper(volume);
		c = volume[0];
	}

	return c;
}

#include "volume_map.hpp"

std::string const volume_master::get_pathname(std::string const& _volume, std::string const& _volume_map_file)
{
	std::string v(_volume);
	boost::trim(v);

	if(!_volume_map_file.empty() &&
		(v.find_first_of(':') != std::string::npos))
	{		
		std::string m = v.substr(0, _volume.find_first_of(':'));
		boost::algorithm::to_upper(m);
		char letter = m[0];

		volume_map vmap(_volume_map_file);
		std::string label = vmap.get_label(letter);

		if(!label.empty())
		{
			letter = get_volume_letter(label);
			if(letter != ' ') // now we have the actual letter
				v[0] = letter;
		}
	}

	return v;
}